/*
 *  statement_execution.c
 *  
 *
 *  Created by Yi Lin on 11-5-7.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

/* statement executions*/
enum execution_type {
        RETURN;
        BREAK;
        ERROR;
        FINISHED;
};

struct s_execution {
        e_evaluation evaluation;
        enum execution_type type;
};

struct s_execution INVALID_EXECUTION = {invalid_evaluation, ERROR};
struct s_execution DEFAULT_EXECTION = {default_evalution, FINISHED};

struct access_talbe{

};

struct s_execution execute_call_stmt(char *event_id, struct access_table *access_table){
        
        /* look up the event function using event_id provided */
        struct f_function function = look_up_event(event_id);
        
        if (function == NULL) {
                return INVALID_EXECUTION;
        }
        
        return execute_event(function->s_list, access_table, EVENT);
        
}

struct s_execution execute_event
（struct s_list *statements, struct access_table *access_table）{
        
        struct s_execution ret 
                = execute_statement_list(struct s_list *statements, access_table);      
        
        if (ret.type != FINISHED) {
                return INVALID_EXECUTION;
        }
}

struct s_execution execute_statement_list
(struct s_list *statements, int contex, struct access_table *access_table) {
        
        struct s_node *p = s_list->first;
        struct s_execution ret;
        
        while (p != NULL) {
                /* execute one statement*/
                ret = execute_statement(p->statement);
                
                // return statement in a function
                if(ret == INVALID_EXECUTION)
                        return INVALID_EXECUTION;
                
                if(ret.type == RETURN && contex == FUNCTION)
                        return ret;
                else 
                        return INVALID_EXECUTION;
                
                // break statement in a loop
                if(ret.type == BREAK && contex == LOOP) {
                        ret.type = FINISHED;
                        return ret;
                }
                else 
                        return INVALID_EXECUTION;
                
                
                p = p->next;
        }
        
        ret.type = FINISHED;
        return ret;
}


struct s_execution execute_statement
(struct s_statement *stmt, int contex, struct access_table *access_table){
        
        switch (stmt->cate) {
                case S_EXPRESSION:
                        return execute_expression_stmt(stmt->spec.expression.expression);
                        
                case S_IF:
                        return execute_if_else_stmt(stmt->spec.s_if.condition, stmt->spec.s_if.statements, NULL);
                        
                case S_IF_ELSE:
                        return execute_if_else_stmt
                        (stmt->spec.expression.s_if_else.condition, 
                         stmt->spec.s_if_else.truestatements,
                         stmt->spec.s_if_else.falsestatements);
                        
                case S_WHILE:
                        return execute_loop_stmt
                        (stmt->spec.s_while.conditon, stmt->spec.s_while.statements,
                         NULL, NULL, NULL);
                        
                case S_DO_WHILE:
                        return execute_loop_stmt
                        (stmt->spec.s_do_while.condition, stmt->spec.s_do_while.statements,
                         stmt->spec.s_do_while.statements, NULL, NULL);
                        
                case S_FOR:
                        return execute_loop_stmt
                        (stmt->spec.s_for.condition, stmt->spec.s_for.statements,
                         NULL, stmt->spec.s_for.initialization, stmt->spec.s_for.iteration);
                        
                case S_RETURN:
                        if(contex != FUNCTION){
                                return INVALID_EXECUTION;
                        }
                        return execute_return_stmt(stmt->spec.s_return.value);
                        
                case S_CALL:
                        return execute_call_stmt(stmt->spec.s_call.eventidentifier);
                        
                case S_BREAK:
                        return execute_break_stmt();
                        
                default:
                        break;
        }
        
}

/* 
 if (expression) 
 true statements;
 else
 false statements;
 */
struct s_execution execute_if_else_stmt
(struct x_expression *condition, struct s_list *true_statements, struct s_list *false_statements){
        
        struct x_evaluation condition = evaluate_expression(condtion);
        
        if( condition.value )
                return execute_statement_list(true_statements);
        
        else if ( false_statements != NULL)
                return execute_statement_list(false_statements);
        
}


struct s_execution execute_expression_stmt(struct x_expression *expression){
        struct x_evaluation evaluation = evaluate_expression(expression);
        
        if( evaluation == invalid_evaluation)
                return INVALID_EXECUTION;
        else 
                return DEFAULT_EXECUTION;
        
}

/* return expression; */
struct s_execution execute_return_stmt(struct x_expression *value){
        
        struct s_execution ret;
        ret.type = RETURN;
        
        ret.evaluation = evaluate_expression(value);
        
        if(ret.evaluation == invalid_evaluation)
                return INVALID_EXECUTION;
        else 
                return ret;
}

int execute_loop_statement
(struct x_expression *condition, struct s_list *body_statements,
 struct s_list *prerun_statements, struct x_expression init_stmt, struct x_expression iteration){
        
        if(condition == NULL || body_statements == NULL)
                return -1;
        
        /* for "do while", prerun the statements*/
        if( prerun_statements != NULL && !interpret_statement_list(prerun_statements) )
                return -1;
        
        /* for "for", initialization */
        if( init_stmt != NULL && !interpret_statement(init_stmt) )
                return -1;
        
        while (1) {
                struct x_evaluation condition = evaluate_expression(init_stmt);
                
                if ( (int) condition.value == 0) 
                        break;
                
                int ret = interpret_statement_list(body_statements));
                if (ret == -1) 
                        return -1;
                
                if (ret == BREAK)
                        break;
                
                /* for "for", iteration*/
                if( iteration != NULL && !interpret_statement(iteration) )
                        return -1;
        }
        
}


